package com.songyuesheng.app.service.Impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songyuesheng.app.commom.ContextHolder;
import com.songyuesheng.app.commom.Result;
import com.songyuesheng.app.dto.ChangePasswordDto;
import com.songyuesheng.app.dto.LoginDto;
import com.songyuesheng.app.dto.RegisterDto;
import com.songyuesheng.app.enums.HttpCodeEnum;
import com.songyuesheng.app.mapper.UserMapper;
import com.songyuesheng.app.entity.User;
import com.songyuesheng.app.service.OssUploaderService;
import com.songyuesheng.app.service.UserService;
import com.songyuesheng.app.util.BeanCopyUtils;
import com.songyuesheng.app.util.JwtUtil;
import com.songyuesheng.app.vo.LoginVo;
import com.songyuesheng.app.vo.UserInfoVo;
import com.songyuesheng.app.vo.UserListVo;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;

/**
 * @author song
 * @date 2024/3/14 14:02
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private UserMapper userMapper;

    @Value("${oss.avatar-directory}")
    private String avatarDirectory;

    @Resource
    private OssUploaderService ossUploaderService;

    @Override
    public Result<?> login(LoginDto loginDto) {
        //条件构造器
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        //查询输入的用户名和表中用户名相同的用户数据
        queryWrapper.eq(User::getUsername, loginDto.getUsername());
        List<User> selectedList = userMapper.selectList(queryWrapper);
        if (selectedList.isEmpty()) {
            //如果没有查询到用户请求的用户数据,返回用户名错误
            return Result.error(HttpCodeEnum.USER_NOT_EXIST);
        }
        //拿到查询到用户表的第一条数据
        User selected = selectedList.get(0);
        String encodedPassword = selected.getPassword();
        // 判断密码是否正确
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        boolean result = passwordEncoder.matches(loginDto.getPassword(), encodedPassword);
        // 这块逻辑还可以优化
        if (!result) {
            return Result.error(HttpCodeEnum.PASSWORD_ERROR);
        }
        // 生成访问令牌和刷新令牌
        HashMap<String, Object> map = new HashMap<>(2);
        map.put("userId", selected.getId());
        String accessToken = JwtUtil.generateAccessToken(loginDto.getUsername(), map);
        String refreshToken = JwtUtil.generateRefreshToken(loginDto.getUsername(), map);
        //Bean拷贝,返回值字段优化
        UserInfoVo userInfoVo = BeanCopyUtils.copyBean(selected, UserInfoVo.class);
        // 生成头像URL
        if (StrUtil.isNotBlank(userInfoVo.getAvatar())) {
            String avatarUrl = ossUploaderService.generatePresignedUrl(userInfoVo.getAvatar());
            userInfoVo.setAvatar(avatarUrl);
        }
        LoginVo loginVo = new LoginVo(accessToken, refreshToken, userInfoVo);
        return Result.success(loginVo);
    }

    @Override
    public Result<?> register(RegisterDto registerDto) {
        //条件构造器
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        //查询输入的用户名和表中用户名相同的用户数据
        queryWrapper.eq(User::getUsername, registerDto.getUsername());
        List<User> userList = userMapper.selectList(queryWrapper);
        if (!userList.isEmpty()) {
            return Result.error(HttpCodeEnum.USER_EXIST);
        } else if (registerDto.getPassword().equals(registerDto.getConfirmPassword())) {
            PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            String encodePassword = passwordEncoder.encode(registerDto.getPassword());
            registerDto.setPassword(encodePassword);
            //新用户对象
            User registerUser = new User();
            registerUser.setUsername(registerDto.getUsername());
            registerUser.setPassword(registerDto.getPassword());
            registerUser.setNickname(registerDto.getNickname());
            registerUser.setEmail(registerDto.getEmail());
            registerUser.setRole("0");

            int result = userMapper.insert(registerUser);
            if (result == 1) {
                return Result.success();
            } else {
                return Result.error(HttpCodeEnum.REGISTER_FAIL);
            }
        } else {
            //输入的密码和确认密码不同
            return Result.error(HttpCodeEnum.REGISTER_FAIL);
        }
    }

    @Override
    public Result<?> changePassword(ChangePasswordDto changePasswordDto) {
        // 从上下文对象里面获取用户id
        Long userId = ContextHolder.getUserId();
        //根据id查询该用户原密码
        User user = getById(userId);
        String encodePasswordFromDB = user.getPassword();
        //密码加密器
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        if (passwordEncoder.matches(changePasswordDto.getOldPassword(), encodePasswordFromDB)) {
            //用户输入的密码和原密码匹配,可以进行修改密码
            String encodePassword = passwordEncoder.encode(changePasswordDto.getPassword());
            //更新用户对象
            User newUser = new User();
            newUser.setId(userId);
            newUser.setPassword(encodePassword);
            int result = userMapper.updateById(newUser);
            if (result == 1) {
                return Result.success();
            } else {
                return Result.error("修改失败");
            }
        } else {
            return Result.error("原密码输入有误");
        }
    }

    @Override
    public Result<?> selectAllUser() {
        List<User> userList = userMapper.selectList(null);
        List<UserListVo> userListVo = BeanCopyUtils.copyBeanList(userList, UserListVo.class);
        // 为每个用户生成头像URL
        userListVo.forEach(user -> {
            if (StrUtil.isNotBlank(user.getAvatar())) {
                String avatarUrl = ossUploaderService.generatePresignedUrl(user.getAvatar());
                user.setAvatar(avatarUrl);
            }
        });
        return Result.success(userListVo);
    }

    @Override
    public Result<?> updateUserInfo(User user) {
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getId, user.getId());
        int i = userMapper.update(user, lambdaQueryWrapper);
        return Result.success(i);
    }

    @Override
    public Result<?> selectUserByPage(Integer pageNum, Integer pageSize, String username) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<User>().orderByAsc(User::getId);
        queryWrapper.like(StrUtil.isNotBlank(username), User::getUsername, username);
        Page<User> page = new Page<>(pageNum, pageSize);
        Page<User> userPage = userMapper.selectPage(page, queryWrapper);

        // 转换分页结果并生成头像URL
        Page<UserListVo> voPage = new Page<>(pageNum, pageSize, userPage.getTotal());
        List<UserListVo> userListVo = BeanCopyUtils.copyBeanList(userPage.getRecords(), UserListVo.class);
        userListVo.forEach(user -> {
            if (StrUtil.isNotBlank(user.getAvatar())) {
                String avatarUrl = ossUploaderService.generatePresignedUrl(user.getAvatar());
                user.setAvatar(avatarUrl);
            }
        });
        voPage.setRecords(userListVo);
        return Result.success(voPage);
    }

    @Override
    public Result<?> addUser(User user) {
        int i = userMapper.insert(user);
        return Result.success(i);
    }

    @Override
    public Result<?> delUser(Integer id) {
        int i = userMapper.deleteById(id);
        return Result.success(i);
    }

    @Override
    public Result<?> delBatchIds(List<Integer> ids) {
        int i = userMapper.deleteBatchIds(ids);
        return Result.success(i);
    }

    @Override
    public Result<?> updateAvatar(MultipartFile file) {
        try {
            Long userId = ContextHolder.getUserId();
            User user = getById(userId);

            // 1. 上传新头像到OSS
            File tempFile = File.createTempFile("avatar-", ".jpg");
            file.transferTo(tempFile);
            String newObjectKey = ossUploaderService.uploadToOss(tempFile, avatarDirectory);
            tempFile.delete();

            // 2. 如果不是默认头像则删除旧头像
            String oldAvatar = user.getAvatar();
            if (oldAvatar != null && !oldAvatar.equals("avatar-default.png")) {
                ossUploaderService.deleteFile(oldAvatar);
            }

            // 3. 更新数据库
            user.setAvatar(newObjectKey);
            userMapper.updateById(user);

            // 4. 生成并返回新的头像URL
            String avatarUrl = ossUploaderService.generatePresignedUrl(newObjectKey);
            return Result.success(avatarUrl);
        } catch (IOException e) {
            log.error("头像更新失败", e);
            return Result.error("头像更新失败");
        }
    }

    @Override
    public Result<?> getUserInfo() {
        Long userId = ContextHolder.getUserId();
        User user = userMapper.selectById(userId);
        UserInfoVo userInfoVo = BeanCopyUtils.copyBean(user, UserInfoVo.class);
        // 生成头像URL
        if (StrUtil.isNotBlank(userInfoVo.getAvatar())) {
            String avatarUrl = ossUploaderService.generatePresignedUrl(userInfoVo.getAvatar());
            userInfoVo.setAvatar(avatarUrl);
        }
        return Result.success(userInfoVo);
    }
}
